package com.xand.jsonrpc.client;

import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import com.xand.jsonrpc.JSONGenericRequest;
import com.xand.jsonrpc.JSONGenericResponse;
import com.xand.jsonrpc.JSONSerializer;

public class JSONRPCClient {
	private JSONSerializer serializer;

	private HttpClient client;

	private String url;

	public JSONRPCClient(String url) {
		this.url = url;

		serializer = new JSONSerializer("dskfjklsjflksdjfldksjflkdsjklsdfjdslkjf");

		client = new DefaultHttpClient();
	}

	public JSONGenericResponse invoke(JSONGenericRequest req, Class clazz) throws Exception {
		String data = serializer.serializeRequest(req);

		String sResponseData = executePost(data);
		
		return (JSONGenericResponse)serializer.deserialize(sResponseData, clazz);
	}

	private String executePost(String data) throws Exception {
		HttpPost post = new HttpPost(url);

		List<NameValuePair> nvps = new ArrayList<NameValuePair>();
		nvps.add(new BasicNameValuePair("data", data));
		
		post.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));

		HttpResponse response = client.execute(post);
		
		String sResponse = null;
		
		if(response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
			HttpEntity entity = response.getEntity();

			if(entity != null) {
				InputStream is = entity.getContent();

				BufferedInputStream bis = new BufferedInputStream(is);
				ByteArrayOutputStream buf = new ByteArrayOutputStream();
				int result = bis.read();
				while(result != -1) {
					byte b = (byte)result;
					buf.write(b);
					result = bis.read();
				}        
				
				sResponse = buf.toString();
				
				is.close(); // IMPORTANTE: liberar los recursos
			}
		}else{
			// devolver error
		}
		
		return sResponse;
	}
}
